<--- %%NOBANNER%% --> varvalue.sas
 BackForward

/*-------------------<-- Start of Description-->---------------------\
| Retrieve the ith observation for a variable in a dataset;          |
|---------------------<-- End of Description-->----------------------|
|--------------------------------------------------------------------|
|------------<-- Start of Files or Arguments Needed-->---------------|
| arguments:                                                         |
|    indata= the name of a data set;                                 |
|    varname= the 1st, 2nd or a valid variable name do you want;     |
|    which - which observation;                                      |
| Basically, it retrieve the ith observation for the variable in the |
| datset;                                                            |
|-------------<-- End of Files or Arguments Needed-->----------------|
|--------------------------------------------------------------------|
|------------------<-- Start of Files Created-->---------------------|
| Example: %varvalue(ridstat.flup, pt, 2);                           |
| Usage:   %varvalue(indata, varname, which);                        |
\-------------------<-- End of Files Created-->---------------------*/
%macro varvalue(indata, varname, which);
%let _varvaluedsid_=%sysfunc(open(&indata,i));
%if (&_varvaluedsid_) %then %do;
   %if (%chk_type(&varname)=1) %then %do;
      %if (&varname le %sysfunc(attrn(&_varvaluedsid_,NVARS))) %then 
         %let varname=%sysfunc(varname(&_varvaluedsid_,&varname));
      %else %do;
         %put ==> Alert! Dataset %data(&indata) does not have %trim(left(&varname)) variables!;
         Variable Number Over-Limit
         %goto finish;
      %end;
   %end;
   %else %do;
      %let _varvaluevarnum_=%sysfunc(varnum(&_varvaluedsid_,&varname));
      %if (&_varvaluevarnum_ le 0) %then %do;
         %if (%quote(%upcase(%sysfunc(dequote(&varname)))) = %quote(NVARS)) %then
            %let varname=%sysfunc(varname(&_varvaluedsid_,%sysfunc(attrn(&_varvaluedsid_,NVARS))));
         %else %do;
            %put ==> Alert! Dataset %data(&indata) does not have variable %trim(%quote(%left(%quote(%upcase(&varname)))))! A valid variable name;
            %put +++        or a valid option (NVARS, for the last variable for the dataset) is required.;
            Variable Non-Exist
            %goto finish;
         %end;
      %end;
   %end;
   %if (%chk_type(&which) = 1) %then %do;
      %if (&which le 0) %then %do;
         %put ==> Alert! The number of observations must be gt 0;
         Argument Too Small
         %goto finish;
      %end;
      %else %if (&which gt %sysfunc(attrn(&_varvaluedsid_,NOBS))) %then %do;
         %put ==> Alert! Dataset %data(&indata) does not have %trim(%quote(%left(%quote(&which)))) observations!;
         Argument Too Big
         %goto finish;
      %end;
   %end;
   %else %do;
      %if (%quote(%upcase(%sysfunc(dequote(&which)))) = %quote(NOBS)) %then
         %let which=%sysfunc(attrn(&_varvaluedsid_,NOBS));
      %else %do;
	      %put ==> Alert! I can only take a numeric number of observations for variable %trim(%quote(%left(%quote(%upcase(&varname)))));
         %put +++        or NOBS, which is used to retrieve the value of last observation for variable; 
         %put +++        %trim(%quote(%left(%quote(%upcase(&varname))))) in dataset %data(&indata)!;
	      Invalid Argument
	      %goto finish;
      %end;
   %end;
   %syscall set(_varvaluedsid_) ;
   %let _varvaluerc_=%sysfunc(fetchobs(&_varvaluedsid_, &which));
	%if &_varvaluerc_ ne 0 %then
      %put %sysfunc(sysmsg());
	%else %do;
      &&&varname
      %put --> Note: Observation %trim(%quote(%left(%quote(&which)))) of variable %trim(%quote(%left(%quote(%upcase(&varname))))) in dataset %data(&indata) is;
      %put +++       %trim(%quote(%left(%quote(%upcase(&&&varname))))).;
	%end;
   %let _varvaluerc_=%sysfunc(close(&_varvaluedsid_));
%end;
%else %do; Dataset Non-Existed
   %put ==> Alert! Dataset %data(&indata) does not exist!; 
%end;
%finish:;
%mend varvalue;